package com.ease.map.geometry {
    import com.ease.map.Map;
    import com.ease.map.common.enum.AlignmentEnum;
    import com.ease.map.common.enum.GeoTypeEnum;
    import com.ease.map.common.util.Evals;
    import com.ease.map.common.util.GMath;
    import com.ease.map.common.util.Util;
    import com.ease.map.constant.LayerIdConstants;
    import com.ease.map.feature.Feature;
    import com.ease.map.geometry.basetype.Extent;
    import com.ease.map.geometry.basetype.Location;
    import com.ease.map.geometry.basetype.Pixel;
    import com.ease.map.handler.feature.draw.AnchorPoint;
    import com.ease.map.handler.feature.draw.snap.SnapTypeEnum;
    import com.ease.map.layer.GraphicLayer;
    import com.ease.map.style.IStyle;
    import com.ease.map.style.PointStyle;

    import flash.display.Sprite;
    import flash.geom.ColorTransform;

    import mx.controls.Alert;
    import com.ease.map.geometry.AbstractGeometry;
    import com.ease.map.geometry.IPointGeometry;

    [Bindable]
    [RemoteClass(alias="com.kgis.map.model.geometry.PointGeometry")]
    /**
     * 点
     */
    public class PointGeometry extends AbstractGeometry implements IPointGeometry {
        private var _x:Number;

        private var _y:Number;

        private var _z:Number;

        public function PointGeometry(x:Number = 0, y:Number = 0, z:Number = 0) {
            super();
            this.x = x;
            this.y = y;
            this.z = z;
        }

        /**
         * 绘制点几何体
         */
        override public function draw(sprite:Sprite, geoStyle:IStyle, map:Map):void {
            /**feature对象*/
            var symbolSprite:Sprite = null;
            var myMatrix:ColorTransform = null;

            if (!sprite) {
                trace("point sprite为空!");
                return;
            }
            var fea:Feature = sprite as Feature;
            if (!this.isValid()) {
                trace("点几何体不符合规范,point objectid=" + fea.objectId.toString());
                return;
            }
            if (!map) {
                trace("map为空,point objectid=" + fea.objectId.toString());
                return;
            }

            if (!geoStyle) {
                trace("geoStyle为空,point objectid=" + fea.objectId.toString());
                return;
            }

            var pointstyle:PointStyle = geoStyle as PointStyle;

            if (!(pointstyle is PointStyle)) {
                trace("点图形数据有误：objectid=" + fea.objectId.toString() + ",layerid=" + fea.layer.id.toString());
                return;
            }

            var point:Pixel = map.getLayerPxFromLocation(new Location(this.x, this.y));

            var symbolClass:Class = pointstyle.symbolClass;
            if (symbolClass == null) {
                trace("点符号图标不存在");
                return;
            }

            var nAlignMent:int = pointstyle.alignment;
            var nAlpha:int = pointstyle.alpha;

            var nRotation:Number = Evals.evalToNumber((sprite as Feature).fieldsMap, pointstyle.rotation);

            if (!symbolSprite) {
                symbolSprite = new symbolClass() as Sprite;
                myMatrix = new ColorTransform(1, 1, 1, 1, Util.rChannel(pointstyle.color), Util.gChannel(pointstyle.color), Util.bChannel(pointstyle.color));
            }
            symbolSprite.alpha = nAlpha;
            //myMatrix.color = pointstyle.color;
            symbolSprite.transform.colorTransform = myMatrix;

            var scale:Number = 1.0;
            var tempScale:String;
            if (pointstyle.scale.length > map.zoom) {
                tempScale = pointstyle.scale[map.zoom];
            }
            else {
                tempScale = pointstyle.scale[0];
            }
            scale = Evals.getSizeByLevel(tempScale, map.zoom);

            //对齐方式
            if (nAlignMent == AlignmentEnum.LEFTTOP) {
                symbolSprite.y = point.y;
                symbolSprite.x = point.x;
            }
            else if (nAlignMent == AlignmentEnum.MIDETOP) {
                symbolSprite.y = point.y - symbolSprite.width * scale / 2 * Math.cos(90 - nRotation * Math.PI / 180);
                symbolSprite.x = point.x - symbolSprite.width * scale / 2 * Math.sin(90 - nRotation * Math.PI / 180);
            }
            else if (nAlignMent == AlignmentEnum.RIGHTTOP) {
                symbolSprite.y = point.y - symbolSprite.width * scale * Math.cos(Math.PI / 2 - nRotation * Math.PI / 180);
                symbolSprite.x = point.x - symbolSprite.width * scale * Math.sin(Math.PI / 2 - nRotation * Math.PI / 180);
            }
            else if (nAlignMent == AlignmentEnum.LEFTMID) {
                symbolSprite.y = point.y - symbolSprite.height * scale / 2 * Math.cos(0 - nRotation * Math.PI / 180);
                symbolSprite.x = point.x - symbolSprite.height * scale / 2 * Math.sin(0 - nRotation * Math.PI / 180);
            }
            else if (nAlignMent == AlignmentEnum.CENTER) {
                symbolSprite.y = point.y - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale + symbolSprite.height * scale * symbolSprite.height * scale) / 2 * Math.cos(Math.atan(symbolSprite.width * scale / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
                symbolSprite.x = point.x - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale + symbolSprite.height * scale * symbolSprite.height * scale) / 2 * Math.sin(Math.atan(symbolSprite.width * scale / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
            }
            else if (nAlignMent == AlignmentEnum.RIGHTMID) {
                symbolSprite.y = point.y - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale + symbolSprite.height * scale * symbolSprite.height * scale / 4) * Math.cos(Math.atan(symbolSprite.width * scale * 2 / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
                symbolSprite.x = point.x - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale + symbolSprite.height * scale * symbolSprite.height * scale / 4) * Math.sin(Math.atan(symbolSprite.width * scale * 2 / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
            }
            else if (nAlignMent == AlignmentEnum.LEFTBOTTOM) {
                symbolSprite.y = point.y - symbolSprite.height * scale * Math.cos(0 - nRotation * Math.PI / 180);
                symbolSprite.x = point.x - symbolSprite.height * scale * Math.sin(0 - nRotation * Math.PI / 180);
            }
            else if (nAlignMent == AlignmentEnum.MIDBOTTOM) {
                symbolSprite.y = point.y - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale / 4 + symbolSprite.height * scale * symbolSprite.height * scale) * Math.cos(Math.atan(symbolSprite.width * scale * 0.5 / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
                symbolSprite.x = point.x - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale / 4 + symbolSprite.height * scale * symbolSprite.height * scale) * Math.sin(Math.atan(symbolSprite.width * scale * 0.5 / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
            }
            else if (nAlignMent == AlignmentEnum.RIGHTBOTTOM) {
                symbolSprite.y = point.y - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale + symbolSprite.height * scale * symbolSprite.height * scale) * Math.cos(Math.atan(symbolSprite.width * scale / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
                symbolSprite.x = point.x - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale + symbolSprite.height * scale * symbolSprite.height * scale) * Math.sin(Math.atan(symbolSprite.width * scale / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
            }

            symbolSprite.rotation = nRotation;

            symbolSprite.scaleX = scale;
            symbolSprite.scaleY = scale;

            sprite.addChild(symbolSprite);

            //编辑状态显示锚点
            if (fea.editing) {
                drawAnchorPoint(sprite, map);
            }

        }

        override public function getExtent():Extent {
            return new Extent(x, y, x, y);
        }

        override public function getGeometryType():int {
            return GeoTypeEnum.POINTGEOMETRY;
        }

        public function get y():Number {
            return _y;
        }

        public function set y(value:Number):void {
            _y = value;
        }

        public function get x():Number {
            return _x;
        }

        public function set x(value:Number):void {
            _x = value;
        }

        public function get z():Number {
            return _z;
        }

        public function set z(value:Number):void {
            _z = value;
        }

        public function equals(point:PointGeometry):Boolean {
            var equals:Boolean = false;
            if (point != null) {
                equals = ((this._x == point.x && this._y == point.y && this._z == point.z) || (isNaN(this._x) && isNaN(this._y) && isNaN(point.x) && isNaN(point.y)));
            }
            return equals;
        }

        override public function getTolerancePoint(mousePoint:PointGeometry, distance:Number, snapPoint:PointGeometry):int {
//            trace(mousePoint.x + ";" + mousePoint.y);
//            trace("捕捉点距离:" + GMath.TwoPointDistance(this, mousePoint));
//            trace("捕捉点容差:" + distance);
            if (GMath.TwoPointDistance(this, mousePoint) < distance) {
                snapPoint.x = this.x;
                snapPoint.y = this.y;
                return SnapTypeEnum.SNAP_OVERTEX;
            }
            else {
                return SnapTypeEnum.NO_SNAPS;
            }
        }

        public function toString():String {
            return "PointGeometry [x=" + x + ", y=" + y + ",z=" + z + "]";
        }

        public function clone():PointGeometry {
            var point:PointGeometry = new PointGeometry();
            point.x = this.x;
            point.y = this.y;
            point.z = this.z;
            return point;
        }

        override public function getLabelLocation():Location {
            return new Location(this.x, this.y);
        }

        override public function offset(location:Location):void {
            this.x = this.x + location.x;
            this.y = this.y + location.y;
        }

        /**
         * 画锚点
         */
        public function drawAnchorPoint(sprite:Sprite, map:Map):void {
            var i:int = 0;
            var k:int = 0;
            var point:Pixel = null;
            var anchor:AnchorPoint;
            var bfind:Boolean = false;

            point = map.getLayerPxFromLocation(new Location(this.x, this.y));
            var anchorLayer:GraphicLayer = map.getLayerById(LayerIdConstants.ANCHORLAYER_LAYERID) as GraphicLayer;
            if (null == anchorLayer) {
                Alert.show("---error ,anchorLayer is null ,where draw pointgeometry", "临时为了测试bug");
//                trace("---error ,anchorLayer is null ,where draw pointgeometry");
            }
            var numLayers:int = map.layers.length;
            if (map.getLayerIndex(anchorLayer) != numLayers - 1) {
                map.changeLayerIndex(anchorLayer, 0);
            }
            //trace("画锚点------------------------:" + point.x + "  " + point.y);
            bfind = false;
            var childnum:Number = anchorLayer.numChildren;
            for (k = 0; k < childnum; k++) {
                if (anchorLayer.getChildAt(k) is AnchorPoint) {
                    if ((anchorLayer.getChildAt(k) as AnchorPoint).geoPoint == this) {
                        //锚点已经存在
                        anchor = anchorLayer.getChildAt(k) as AnchorPoint;
                        bfind = true;
                    }
                }
            }
            if (!bfind) {
                anchor = new AnchorPoint();
                anchorLayer.addChild(anchor);
                anchor.pointIndex = 0;
                anchor.parentFeature = sprite as Feature;
                anchor.geoPoint = this;
            }
            anchor.x = point.x;
            anchor.y = point.y;

        }

        override public function isValid():Boolean {
            return true;
        }

        override public function hasPoint(point:PointGeometry):Boolean {
            if (this.x == point.x && this.y == point.y && this.z == point.z) {
                return true;
            }
            return false;
        }

    }
}